import { Graph, Shape } from '@antv/x6';
import plugins from '../plugins';

type InputsType = {
  edgeId: string;
  targetNode: string;
}[] | true

class X6GraphManager {
  private static instance: Graph | null = null;

  static init(container: HTMLElement, width?: number, height?: number, options?: object): Graph {
    if (!X6GraphManager.instance) {
      X6GraphManager.instance = new Graph({
        container,
        autoResize:true,
        // width: width || 800,
        // height: height || 600,
        grid: {
          size: 10,
          visible: true, // 网格背景是否可见
        },
        onPortRendered({ contentContainer, port, node }) {
          if (contentContainer instanceof HTMLElement) {
            const text = node.portProp(port.id, 'tip') as string
            contentContainer.addEventListener('mouseenter', (e: MouseEvent) => {
              console.log('mouseenter', e);
            })
            contentContainer.addEventListener('mouseleave', () => {
              console.log('mouseleave');
            })
          }
        },
        connecting: {
          // 连接线
          router: 'manhattan',
          connector: {
            name: 'rounded',
            args: {
              radius: 8,
            },
          },
          anchor: 'center',
          connectionPoint: 'anchor',
          allowBlank: false,
          snap: {
            radius: 20,
          },
          createEdge() {
            return new Shape.Edge({
              attrs: {
                line: {
                  stroke: '#A2B1C3',
                  strokeWidth: 2,
                  targetMarker: {
                    name: 'block',
                    width: 12,
                    height: 8,
                  },
                },
              },
              zIndex: 0,
            })
          },
          validateConnection({
            sourceCell,
            targetCell,
            sourceMagnet,
            targetMagnet,
          }) {
            // 不能连接自身
            if (sourceCell === targetCell) {
              return false
            }
            // 必须连接到连接桩上
            if (!sourceMagnet || !targetMagnet) {
              return false
            }
            console.log('sourceMagnet', sourceMagnet?.getAttribute('port'));
            console.log('targetMagnet', targetMagnet?.getAttribute('port'));
            // 只能连接到顶部连接桩上
            if (
              !sourceMagnet ||
              sourceMagnet.getAttribute('port-group') === 'top'
            ) {
              return false
            }
            // 不能连接到底部和右侧连接桩上
            if (
              !targetMagnet ||
              targetMagnet.getAttribute('port-group') === 'bottom' ||
              targetMagnet.getAttribute('port-group') === 'right'
            ) {
              return false
            }

            const edges = this.getEdges();
            const portId = sourceMagnet!.getAttribute('port');
            const edge = edges.map((edge) => edge.getSourcePortId());
            const edgeIds = edge.filter((item)=>item === portId);
            if(edgeIds.length > 1) return false;
            return true
          },
        },
        highlighting: {
          // 连接桩可以被连接时在连接桩外围围渲染一个包围框
          magnetAvailable: {
            name: 'stroke',
            args: {
              attrs: {
                fill: '#fff',
                stroke: '#A4DEB1',
                strokeWidth: 6,
              },
            },
          },
          // 连接桩吸附连线时在连接桩外围围渲染一个包围框
          magnetAdsorbed: {
            name: 'stroke',
            args: {
              attrs: {
                fill: '#fff',
                stroke: '#31d0c6',
                strokeWidth: 6,
              },
            },
          },
        },
        mousewheel: {
          enabled: true,
          modifiers: ['ctrl'],
        },
        ...options,
      });
      // 批量 use 插件
      plugins.forEach((plugin) => {
        X6GraphManager.instance!.use(plugin);
      });
    }
    return X6GraphManager.instance;
  }


  // 设置线变色
  static setLineColor(inputs?:InputsType){
      const graph = X6GraphManager.instance;
      if(!graph) return;
      if(inputs === true){
        graph.getEdges().forEach((edge) => {
          edge.attr('line/style/animation', 'none');
          edge.attr({
            line: {
              stroke: '#1890ff',
              strokeWidth: 1,
              strokeDasharray: 'none'
            },
          })
        })
      }else if(inputs){
        const ids = inputs.map((input)=>input.edgeId);
        graph.getEdges().forEach((edge) => {
          if (ids.includes(edge.id)) {
            // 设置虚线样式和动画
            edge.attr({
              line: {
                stroke: '#1890ff',
                strokeWidth: 2,
                strokeDasharray: '5,5',
                strokeDashoffset: 0
              }
            });
            // 直接设置动画属性
            edge.attr('line/style/animation', 'running-line 2s infinite linear');
          }
        })
      }else{
        graph.getEdges().forEach((edge) => {
          // 移除动画并恢复默认样式
          edge.attr('line/style/animation', 'none');
          edge.attr({
            line: {
              stroke: 'rgb(162,171,195)',
              strokeWidth: 1,
              strokeDasharray: 'none'
            },
          })
        })
      }
  }

  // 设置线上文字
  static setLineText(id: string, text: string){
    const graph = X6GraphManager.instance;
    if(!graph) return;
    graph.getEdges().forEach((edge) => {
      if(edge.id === id){
        edge.removeLabelAt(0)
        edge.appendLabel({
          attrs: {
            text: {
              text: text,
            },
            body: {},
          },
          position: 0.2,
        })
      }
    })
  }

  // 移除工具栏
  static removeToolbar(){
    const graph = X6GraphManager.instance;
    if(!graph) return;
    graph.getNodes().forEach(node=>{
      node.removeTools()
    });
  }

  // 导出图片
  static exportImage(){
    const graph = X6GraphManager.instance;
    if(!graph) return;
    graph.exportPNG(new Date().getTime() + '', {
      padding: 20,
    })
  }


  // 将画布中元素居中展示
  static center(){
    const graph = X6GraphManager.instance;
    if(!graph) return;
    graph.centerContent();
  }


  static getInstance(): Graph | null {
    return X6GraphManager.instance;
  }

  static dispose() {
    if (X6GraphManager.instance) {
      X6GraphManager.instance.dispose();
      X6GraphManager.instance = null;
    }
  }
}

export default X6GraphManager; 